package com.leon.datalink.web.testcontroller;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.leon.datalink.core.utils.JacksonUtils;
import org.springframework.web.bind.annotation.*;

import java.lang.management.*;
import java.util.Random;

/**
 * Actuator metrics controller for development
 */
@RestController
@RequestMapping("/actuator/metrics")
@CrossOrigin(origins = "*", maxAge = 3600)
public class ActuatorController {

    private final Random random = new Random();
    private final OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
    private final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
    private final RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
    private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
    private final ClassLoadingMXBean classBean = ManagementFactory.getClassLoadingMXBean();

    @GetMapping("/system.cpu.count")
    public Object getCpuCount() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "system.cpu.count");
        result.put("description", "The number of processors available to the Java virtual machine");
        result.putNull("baseUnit");
        
        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", Runtime.getRuntime().availableProcessors());
        measurements.add(measurement);
        
        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/system.cpu.usage")
    public Object getCpuUsage() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "system.cpu.usage");
        result.put("description", "The recent cpu usage for the whole system");
        result.put("baseUnit", "percent");
        
        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", random.nextDouble() * 0.5); // 0-50% CPU usage
        measurements.add(measurement);
        
        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/process.cpu.usage")
    public Object getProcessCpuUsage() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "process.cpu.usage");
        result.put("description", "The recent cpu usage for the Java Virtual Machine process");
        result.put("baseUnit", "percent");
        
        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", random.nextDouble() * 0.3); // 0-30% process CPU usage
        measurements.add(measurement);
        
        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.memory.max")
    public Object getJvmMemoryMax() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.memory.max");
        result.put("description", "The maximum amount of memory in bytes that can be used for memory management");
        result.put("baseUnit", "bytes");
        
        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        measurement.put("value", memoryBean.getHeapMemoryUsage().getMax());
        measurements.add(measurement);
        
        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.memory.used")
    public Object getJvmMemoryUsed() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.memory.used");
        result.put("description", "The amount of used memory");
        result.put("baseUnit", "bytes");
        
        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        measurement.put("value", memoryBean.getHeapMemoryUsage().getUsed());
        measurements.add(measurement);
        
        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/process.start.time")
    public Object getProcessStartTime() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "process.start.time");
        result.put("description", "Start time of the process since unix epoch");
        result.put("baseUnit", "seconds");
        
        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        
        RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
        measurement.put("value", runtimeBean.getStartTime() / 1000.0);
        measurements.add(measurement);
        
        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/process.uptime")
    public Object getProcessUptime() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "process.uptime");
        result.put("description", "The uptime of the Java virtual machine");
        result.put("baseUnit", "seconds");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");

        RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
        measurement.put("value", runtimeBean.getUptime() / 1000.0);
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.memory.committed")
    public Object getJvmMemoryCommitted() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.memory.committed");
        result.put("description", "The amount of memory in bytes that is committed for the Java virtual machine to use");
        result.put("baseUnit", "bytes");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", memoryBean.getHeapMemoryUsage().getCommitted());
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.buffer.memory.used")
    public Object getJvmBufferMemoryUsed() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.buffer.memory.used");
        result.put("description", "An estimate of the memory that the Java virtual machine is using for this buffer pool");
        result.put("baseUnit", "bytes");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", random.nextLong(1000000, 10000000)); // 模拟缓冲区内存使用
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.buffer.count")
    public Object getJvmBufferCount() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.buffer.count");
        result.put("description", "An estimate of the number of buffers in the pool");
        result.putNull("baseUnit");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", random.nextInt(100, 1000)); // 模拟缓冲区数量
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.threads.daemon")
    public Object getJvmThreadsDaemon() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.threads.daemon");
        result.put("description", "The current number of live daemon threads");
        result.putNull("baseUnit");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", threadBean.getDaemonThreadCount());
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.threads.live")
    public Object getJvmThreadsLive() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.threads.live");
        result.put("description", "The current number of live threads including both daemon and non-daemon threads");
        result.putNull("baseUnit");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", threadBean.getThreadCount());
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.threads.peak")
    public Object getJvmThreadsPeak() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.threads.peak");
        result.put("description", "The peak live thread count since the Java virtual machine started or peak was reset");
        result.putNull("baseUnit");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", threadBean.getPeakThreadCount());
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.classes.loaded")
    public Object getJvmClassesLoaded() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.classes.loaded");
        result.put("description", "The number of classes that are currently loaded in the Java virtual machine");
        result.putNull("baseUnit");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", classBean.getLoadedClassCount());
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }

    @GetMapping("/jvm.classes.unloaded")
    public Object getJvmClassesUnloaded() {
        ObjectNode result = JacksonUtils.createEmptyJsonNode();
        result.put("name", "jvm.classes.unloaded");
        result.put("description", "The total number of classes unloaded since the Java virtual machine has started execution");
        result.putNull("baseUnit");

        ArrayNode measurements = JacksonUtils.createEmptyArrayNode();
        ObjectNode measurement = JacksonUtils.createEmptyJsonNode();
        measurement.put("statistic", "VALUE");
        measurement.put("value", classBean.getUnloadedClassCount());
        measurements.add(measurement);

        result.set("measurements", measurements);
        return result;
    }
}
